package org.skycloud.mybatis.dialect;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.skycloud.mybatis.dialect.impl.DB2Dialect;
import org.skycloud.mybatis.dialect.impl.MySQLDialect;
import org.skycloud.mybatis.dialect.impl.OracleDialect;
import org.skycloud.mybatis.dialect.impl.PostgreSQLDialect;
import org.skycloud.mybatis.dialect.impl.SQLiteDialect;
import org.skycloud.mybatis.utils.DatabaseIdUtils;

public class DefaultDialectFactory implements DialectFactory {

	private final DataSource dataSource;

	public DefaultDialectFactory(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	@Override
	public final Dialect getDialect() {
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
			DatabaseMetaData metaData = conn.getMetaData();
			return getDialectFromDatabaseProductName(metaData.getDatabaseProductName());
		} catch (SQLException e) {
			throw new IllegalStateException(
					"Can't get dialect from DataSource. You may implement your own DialectFactory or set Dialect to RowBoundsInterceptor directly.",
					e);
		} finally {
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException ignore) {
				}
			}
		}
	}

	protected Dialect getDialectFromDatabaseProductName(String databaseProductName) {
		String databaseId = DatabaseIdUtils.getDatabaseId(databaseProductName);

		if (databaseId != null) {
			if ("oracle".equals(databaseId)) {
				return new OracleDialect();
			} else if ("db2".equals(databaseId)) {
				return new DB2Dialect();
			} else if ("mysql".equals(databaseId)) {
				return new MySQLDialect();
			} else if ("postgresql".equals(databaseId)) {
				return new PostgreSQLDialect();
			} else if ("sqlite".equals(databaseId)) {
				return new SQLiteDialect();
			} else {
				throw new IllegalStateException("Can't get dialect from DataSource with database product name ["
						+ databaseProductName + "].");
			}
		} else {
			throw new IllegalStateException("Can't get dialect from DataSource with database product name ["
					+ databaseProductName + "].");
		}
	}
}
